package com.augurit.gzcgwsp.readAndParseXML.service.impl;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Random;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
import org.drools.lang.DRLParser.template_id_return;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.augurit.common.syslog.tool.SysTraceLogWriter;
import com.augurit.gzcgwsp.readAndParseXML.service.IParseXMLService;
import com.augurit.gzcgwsp.webservice.SFTPUtil;
import com.augurit.gzcgwsp.ywcmn.service.IYwComQyxxService;
import com.augurit.gzcgwsp.ywcmn.service.IYwComSjclService;
import com.augurit.gzcgwsp.ywcmn.web.form.YwComQyxxForm;
import com.augurit.gzcgwsp.ywcmn.web.form.YwComSjclForm;

/**
 * 设施改动、企业资质、户外广告通用的方法
 * @author Administrator
 *
 */
@Service
@Transactional
public class ParseXMLServiceImpl implements IParseXMLService{
	Logger logger = (Logger) LoggerFactory.getLogger(ParseXMLServiceImpl.class);
	@Autowired
	private IYwComQyxxService ywComQyxxService;
	@Autowired
	private IYwComSjclService ywComSjclService;

	private Map<String, String> xmlKeyValueMap = new HashMap<String, String>();
	private Map<String, String> xmlHeadKeyValueMap = new HashMap<String, String>();
	
	/**
	 * 解析xml数据部分
	 * @param map  数据库和网站端传过来的xml标签对应map
	 * @param xmlFilePath   xml路径
	 * @param feedbackPath  解析正确反馈xml存放路径
	 * @param exceptionPath  解析异常反馈xml存放路径
	 * @throws DocumentException
	 */
	public void initXmlFile(Map<String,String> map,String xmlFilePath,String feedbackPath,String exceptionPath) throws Exception{
		String xmlKey = "";
		String xmlKeyValue = "";
		File file = new File(xmlFilePath);
		SAXReader reader = new SAXReader();
		Document read_doc = null;

		read_doc = reader.read(file);

		List list = read_doc.selectNodes("//ApprovalData");
		// for (Node n : list) {
		for (int i = 0; i < list.size(); i++) {
			// 1.在for循环里面定义一个数组，把解析到的数据保存到数组里面
			// 2.在for循环外面定义一个list，把数组保存到list里面
			Node n = (Node) list.get(i);
			Element e = (Element) n;			
			for(String mapKey : map.keySet()){
				System.out.println("KEY = "+mapKey);
				if("approvalNo".equals(mapKey) || "businessCode".equals(mapKey) || "sendTime".equals(mapKey)){
				}else{
					xmlKeyValue = e.selectSingleNode((String)(map.get(mapKey))).getText().trim();
					System.out.println("mapKey = "+mapKey);
					System.out.println("xmlKeyValue = "+xmlKeyValue);
					xmlKeyValueMap.put(mapKey, xmlKeyValue);
				}
			}			
		}
		String approvalNo = this.getApprovalId(file);
		xmlKeyValueMap.put("approvalNo", approvalNo);//把预受理号放进去
		String businessCode = this.getBusinessCodeOrSendTime(file,"businessCode");
		xmlKeyValueMap.put("businessCode", businessCode);//把业务代码放进去
		String sendTime = this.getBusinessCodeOrSendTime(file,"sendTime");
		xmlKeyValueMap.put("sendTime", sendTime);//把网上提交时间放进去
	}
	
	/**
	 * 通过数据库和网站端传过来的xml标签对应map的key,获得xml中对应标签的值
	 * @param mapKey
	 * @return xml中对应标签的值
	 */
	public String getMapValue(String mapKey){			
		return this.xmlKeyValueMap.get(mapKey);
	}

	/**
	 * 解析xml头部
	 * @param map  数据库和网站端传过来的xml标签对应map
	 * @param xmlFilePath   xml路径
	 * @param feedbackPath  解析正确反馈xml存放路径
	 * @param exceptionPath  解析异常反馈xml存放路径
	 * @throws DocumentException
	 */
	public Map<String,String> initXmlFileHead(Map<String, String> map, File file,
			String feedbackPath, String exceptionPath) throws Exception {
		String xmlKeyValue = "";
		//File file = new File(file.getPath());
		SAXReader reader = new SAXReader();
		Document read_doc = null;

		read_doc = reader.read(file);

		//List list = read_doc.selectNodes("//ApprovalData");
		List list = read_doc.selectNodes("//head");
		// for (Node n : list) {
		for (int i = 0; i < list.size(); i++) {
			// 1.在for循环里面定义一个数组，把解析到的数据保存到数组里面
			// 2.在for循环外面定义一个list，把数组保存到list里面
			Node n = (Node) list.get(i);
			Element e = (Element) n;			
			for(String mapKey : map.keySet()){
				xmlKeyValue = e.selectSingleNode((String)(map.get(mapKey))).getText().trim();
				xmlHeadKeyValueMap.put(mapKey, xmlKeyValue);
			}			
		}	
		xmlHeadKeyValueMap.put("controlFile", file.getName());//把文件名放进去
		String receiver = this.getReceiver(file);
		xmlHeadKeyValueMap.put("receiver", receiver);//把接收code放进去
		String approvalId = this.getReceiver(file);
		xmlHeadKeyValueMap.put("approvalId", approvalId);//把预受理ID放进去
		return xmlHeadKeyValueMap;
	}
	
	/**
	 * 通过数据库和网站端传过来的xml标签对应map的key,获得xml中头部对应标签的值
	 * @param mapKey
	 * @return xml中头部对应标签的值
	 */
	public String getHeadMapValue(String mapKey){			
		return this.xmlHeadKeyValueMap.get(mapKey);
	}
	
	
	/**
	 * 生成解析成功的反馈xml
	 * @param map
	 * @return
	 */
	public Document createFeedbackXML (Map map){
		Document document = DocumentHelper.createDocument();
		//生成一个接点
		Element feedback = document.addElement("feedback");
		//生成feedback的一个接点
		Element sn = feedback.addElement("sn");
		//生成sn里面的值
		sn.addText((String)map.get("sn"));
		//生成feedback的一个接点
		Element exchangeType = feedback.addElement("exchangeType");
		//生成exchangeType里面的值
		exchangeType.addText("MS");
		//生成feedback的一个接点
		Element sender = feedback.addElement("sender");
		//生成sender里面的值
		sender.addText((String)map.get("receiver"));//放接收端code
		//生成feedback的一个接点
		Element receiver = feedback.addElement("receiver");
		//生成receiver里面的值
		receiver.addText((String)map.get("sender"));
		//生成feedback的一个接点
		Element businessCode = feedback.addElement("businessCode");
		//生成businessCode里面的值
		businessCode.addText((String)map.get("businessCode"));
		//生成feedback的一个接点
		Element controlFile = feedback.addElement("controlFile");
		//生成controlFile里面的值
		controlFile.addText((String)map.get("controlFile"));
		//生成feedback的一个接点
		Element receiveTime = feedback.addElement("receiveTime");
		//生成receiveTime里面的值
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		Date dateTemp = new Date();
		String date = sdf.format(dateTemp);
		receiveTime.addText(date);
		//生成feedback的一个接点
		Element status = feedback.addElement("status");
		//生成status里面的值
		status.addText("XML解析成功！");
		
		
		//生成feedback的一个接点
		Element receiveData = feedback.addElement("receiveData");
		//生成receiveData的一个接点
		Element approvalId = receiveData.addElement("approvalId");
		//生成approvalId里面的值
		approvalId.addText((String)map.get("approvalId"));
		
		//生成id里面的参数值
		//id.addAttribute("name", "id");
		return document;
	}
	
	/**
	 * 写入xml文件地址
	 * @param document 所属要写入的内容
	 * @param outFilePath 文件存放的地址
	 * @param file 	文件
	 */
	public void writeFeedbackXML(Document document, String outFilePath,File file) throws Exception{
		String fileNameTemp = file.getName();
		String fileName = ""; 
		int beginIndex = fileNameTemp.indexOf("_000001");
		String fileName1 = fileNameTemp.substring(0, beginIndex+1);
		String fileName2 = fileNameTemp.substring(beginIndex+1,
				fileNameTemp.length());
		fileName = fileName1 + "FEEDBACK_" + fileName2;
		
		//设置文件编码
		OutputFormat xmlFormat = OutputFormat.createPrettyPrint();
		xmlFormat.setEncoding("UTF-8");
		//创建写文件方法
		//XMLWriter xmlWriter = new XMLWriter(fileWriter,xmlFormat);
		//写入文件
		//读取文件
		XMLWriter  xmlWriter = new XMLWriter(new FileOutputStream(outFilePath+File.separator+fileName), xmlFormat);
		xmlWriter.write(document);
		//关闭
		xmlWriter.close();
		//上传到另外一台机器
//		SFTPUtil.uploadOtherFileForFx(outFilePath+File.separator+fileName, outFilePath+File.separator+fileName);
    }
	
	/*
	 * 生成 交换异常反馈的XML
	 */
	public Document createExceptionXML (Map map){
		Document document = DocumentHelper.createDocument();
		//生成一个接点
		Element feedback = document.addElement("exception");
		//生成feedback的一个接点
		Element sn = feedback.addElement("sn");
		//生成sn里面的值
		sn.addText((String)map.get("sn"));
		//生成feedback的一个接点
		Element exchangeType = feedback.addElement("exchangeType");
		//生成exchangeType里面的值
		exchangeType.addText("MS");
		//生成feedback的一个接点
		Element sender = feedback.addElement("sender");
		//生成sender里面的值
		sender.addText((String)map.get("receiver"));
		//生成feedback的一个接点
		Element receiver = feedback.addElement("receiver");
		//生成receiver里面的值
		receiver.addText((String)map.get("sender"));
		//生成feedback的一个接点
		Element businessCode = feedback.addElement("businessCode");
		//生成businessCode里面的值
		businessCode.addText((String)map.get("businessCode"));
		//生成feedback的一个接点
		Element controlFile = feedback.addElement("controlFile");
		//生成controlFile里面的值
		controlFile.addText((String)map.get("controlFile"));
		//生成feedback的一个接点
		Element time = feedback.addElement("time");
		//生成time里面的值
		Date dateTemp = new Date();
		SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		String  date = sdf.format(dateTemp);
		time.addText(date);
		//生成feedback的一个接点
		Element errorCode = feedback.addElement("errorCode");
		//生成errorCode里面的值
		errorCode.addText((String)map.get("errorCode"));
		//生成feedback的一个接点
		Element errorStatus = feedback.addElement("errorStatus");
		//生成errorStatus里面的值
		errorStatus.addText((String)map.get("errorStatus"));
		//生成feedback的一个接点
		Element errorStack = feedback.addElement("errorStack");
		//生成errorStack里面的值
		errorStack.addText((String)map.get("errorStack"));		
		//生成feedback的一个接点
		Element errorData = feedback.addElement("errorData");
		//生成errorData的一个接点
		Element approvalId = errorData.addElement("approvalId");
		//生成approvalId里面的值
		approvalId.addText((String)map.get("approvalId"));
		
		//生成id里面的参数值
		//id.addAttribute("name", "id");
		return document;
	}
	
	/**
	 * 写入xml文件地址
	 * @param document 所属要写入的内容
	 * @param outFilePath 文件存放的地址
	 * @param file 文件
	 */
	public void writeExceptionXML(Document document, String outFilePath,File file) throws Exception{
		String fileNameTemp = file.getName();
		String fileName = "";
		int beginIndex = fileNameTemp.indexOf("_000001");
		String fileName1 = fileNameTemp.substring(0, beginIndex+1);
		String fileName2 = fileNameTemp.substring(beginIndex+1,
				fileNameTemp.length());
		fileName = fileName1 + "EXCEPTION_" + fileName2;
		
		//设置文件编码
		OutputFormat xmlFormat = OutputFormat.createPrettyPrint();
		xmlFormat.setEncoding("UTF-8");
		XMLWriter  xmlWriter = new XMLWriter(new FileOutputStream(outFilePath+File.separator+fileName), xmlFormat);
		xmlWriter.write(document);
		//关闭
		xmlWriter.close();
		//上传到另外一台机器
//		SFTPUtil.uploadOtherFileForFx(outFilePath+File.separator+fileName, outFilePath+File.separator+fileName);
    }	
	
	/**
	 * 把文件移走
	 * @param filePath 从这里读文件
	 * @param newPath 移到这里
	 * @param fileName 文件名  暂时没有用到
	 */
	public void removeXML(String filePath,String newPath,String fileName){
		//把文件移走
		// 剪切文件夹
		int bytesum = 0;
		int byteread = 0;
		// 从这里取数据
		File oldfile = new File(filePath);
		if (oldfile.exists()) { // 文件存在时
			InputStream inStream;
			try {
				inStream = new FileInputStream(oldfile);
				// 读入原文件
				FileOutputStream fs = new FileOutputStream(newPath);
				byte[] buffer = new byte[1024];
				while ((byteread = inStream.read(buffer)) != -1) {
					bytesum += byteread; // 字节数 文件大小
					fs.write(buffer, 0, byteread);
				}
				inStream.close();
				oldfile.delete(); // 删除文件						
			} catch (Exception e) {
				// TODO Auto-generated catch block
				logger.error("(接口)移走文件失败"+SysTraceLogWriter.MESSAGE_SEPARATOR + e.getMessage(), e);
				e.printStackTrace();
			}
		} // 剪切文件结束
	}
	
	/**
	 * 获得预受理ID
	 * @param file 文件
	 * @return 预受理ID   approvalId
	 */
	public String getApprovalId(File file) throws Exception{
		SAXReader reader = new SAXReader();
		Document read_doc = null;

		read_doc = reader.read(file);
		// 解析受理号
		List unitDataList = read_doc.selectNodes("//UnitData");
		// for(int i = 0;i<unitDataList.size();i++){
		Node unitDataN = (Node) unitDataList.get(0);
		Element unitDataE = (Element) unitDataN;
		String approvalId = unitDataE.selectSingleNode("//UnitValue").getText()
				.trim();
		//map.put("approvalId", approvalId);
		return approvalId;
	}
	
	/**
	 * 解析出预受理ID
	 * @param file 文件
	 * @return
	 */
	public String getReceiver(File file) throws Exception{
		SAXReader reader = new SAXReader();
		Document read_doc = null;

		read_doc = reader.read(file);
		// 解析接收的code
		List receiversList = read_doc.selectNodes("//receivers");
		// for(int i = 0;i<unitDataList.size();i++){
		Node receiversN = (Node) receiversList.get(0);
		Element receiversE = (Element) receiversN;
		String receiver = receiversE.selectSingleNode("//receiver").getText()
				.trim();
		//map.put("approvalId", approvalId);
		return receiver;
	}
	
	/**
	 * 获得业务代码或者网上提交时间
	 * @param file 文件
	 * @return 业务代码   BusinessCode
	 */
	public String getBusinessCodeOrSendTime(File file,String strFlag) throws Exception{
		SAXReader reader = new SAXReader();
		Document read_doc = null;

		read_doc = reader.read(file);
		// 解析接收的code
		List businessCodeList = read_doc.selectNodes("//head");
		// for(int i = 0;i<unitDataList.size();i++){
		Node businessCodeN = (Node) businessCodeList.get(0);
		Element businessCodeE = (Element) businessCodeN;
		String businessCode = businessCodeE.selectSingleNode("//"+strFlag).getText().trim();
		return businessCode;
	}
	
	/**
	 * 解析附件
	 * @param file 文件
	 * @param 文件别名和文件名对应的map
	 */
	public Map<String,String> parseFujian(File file) throws Exception{
		// 另外一种解析附件名字的方法(重复的标签有ID)
		SAXReader reader = new SAXReader();
		Document read_doc = null;
		read_doc = reader.read(file);
		List attachmentList = read_doc
				.selectNodes("//attachments/attachment");
		Map<String,String> map = new HashMap<String,String>();
		for (Iterator it = attachmentList.iterator(); it.hasNext();) {
			Element attachmentEle = (Element) it.next();
			
			String mapKey = "";
			String mapValue = "";
			List displayNameList = (List) attachmentEle.elements("displayName");

			for (Iterator displayNameIt = displayNameList.iterator(); displayNameIt
					.hasNext();) {

				Element displayNameEle = (Element) displayNameIt.next();
				String displayName = displayNameEle.getText();
//				System.out.println("mapKey = " + displayName);
				mapKey = displayName;
			}
			List fileNameList = (List) attachmentEle.elements("fileName");
			String fileName = "";
			for (Iterator fileNameIt = fileNameList.iterator(); fileNameIt
					.hasNext();) {

				Element fileNameEle = (Element) fileNameIt.next();
				fileName = fileNameEle.getText();
//				System.out.println("mapValue = " + fileName);
				mapValue = fileName;
			}
			map.put(mapKey, mapValue);
		}
		return map;
	}
	
	
	/**
	 * 通过申请单位名称，获取申请单位
	 * @param sqdw
	 * @return 企业信息list
	 */
	public YwComQyxxForm getSqdwBySqdw(String sqdw,String templateCode){
		YwComQyxxForm ywComQyxxForm = ywComQyxxService.getFormBySqdw(sqdw,templateCode);		
		return ywComQyxxForm;
	}
	
	/**
	 * 保存异常时，生成异常反馈xml
	 * @param e
	 * @param files
	 * @param ywKeyMapHeadMap
	 * @param ywFeedbackPath
	 * @param ywExceptionPath
	 * @param i
	 */
	public void createSaveOrParseExceptionXml(String errorCode,String errorStatus,Exception e,File[] files,Map<String, String> ywKeyMapHeadMap,
			String ywFeedbackPath,String ywExceptionPath,int i){
		logger.error("(接口)保存数据到数据库异常"+SysTraceLogWriter.MESSAGE_SEPARATOR + e.getMessage(), e);
		
		ByteArrayOutputStream buf = new ByteArrayOutputStream();
		e.printStackTrace(new PrintWriter(buf, true));
		String errorStack = buf.toString();
		Map<String, String> xmlHeadKeyValueMap;
		try {
			xmlHeadKeyValueMap = this.initXmlFileHead(ywKeyMapHeadMap,files[i],ywFeedbackPath,ywExceptionPath);
			// 获得预受理ID
			String approvalId = this.getApprovalId(files[i]);
			xmlHeadKeyValueMap.put("approvalId",approvalId);
			xmlHeadKeyValueMap.put("errorCode",errorCode);
			xmlHeadKeyValueMap.put("errorStatus",errorStatus);
			xmlHeadKeyValueMap.put("errorStack",errorStack);
			this.writeExceptionXML(this.createExceptionXML(xmlHeadKeyValueMap),ywExceptionPath, files[i]);
		} catch (Exception e1) {
			logger.error("(接口)生成异常反馈xml失败"+SysTraceLogWriter.MESSAGE_SEPARATOR + e1.getMessage(), e1);
			e1.printStackTrace();
		}
	}
	
	/**
	 * 处理附件
	 * @param projectPath
	 * @param fileName
	 * @param ywFujianpath
	 * @param ywFeedbackPath
	 * @param ywExceptionPath
	 * @param ywKeyMapHead
	 * @param files
	 * @param fujianMap
	 * @param i
	 * @param qyid
	 * @param ajId
	 * @param tplcode
	 * @throws Exception
	 */
	public void handleFj(String projectPath,String fileName,String ywFujianpath,String ywFeedbackPath,String ywExceptionPath,
			Map<String, String> ywKeyMapHead,File[] files,Map<String, Long> fujianMap,int i,long qyid,long ajId,String tplcode) throws Exception{
		// 解析附件
		Map<String, String> parsefujianMap = this.parseFujian(files[i]);
		for (String parsefujianMapKey : parsefujianMap.keySet()) {
			YwComSjclForm ywComSjclForm = new YwComSjclForm();
			String fujianName = parsefujianMap.get(parsefujianMapKey);
			Long fujianId = fujianMap.get(parsefujianMapKey);
			// 截取文件名后缀
			int startFlag = 0;
			for (int j = 0; j < fujianName.length(); j++) {
				if (fujianName.charAt(j) == '.') {
					startFlag = j;
				}
			}
			String fujianNameType = fujianName.substring(startFlag + 1);// 截取出文件后缀
			String formatDate = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());
			int random = new Random().nextInt(1000000);
			String targetFileName = formatDate + random + "." + fujianNameType;
			String targetFileRealPath = projectPath + "/" + targetFileName;
			ywComSjclForm.setFilename(fujianName);
			ywComSjclForm.setFilepath("/resources/AttacheFile/" + targetFileName);
			ywComSjclForm.setFkid(qyid);
			ywComSjclForm.setFiletype(fujianNameType);
			ywComSjclForm.setAjid(ajId);
			ywComSjclForm.setTplid(fujianId);
			ywComSjclForm.setTplcode(tplcode);

			try {
				ywComSjclService.saveByUpload(ywComSjclForm);// 保存附件信息到附件表
			} catch (Exception e) {
				logger.error("(接口)保存附件信息到附件表异常"+SysTraceLogWriter.MESSAGE_SEPARATOR + e.getMessage(), e);
				e.printStackTrace();
			}

			// 移走附件
			this.removeXML(ywFujianpath+ fujianName, targetFileRealPath, fileName);
		}

		// TODO 生成反馈xml
		Map<String, String> xmlHeadKeyValueMap = this.initXmlFileHead(ywKeyMapHead, files[i],ywFeedbackPath, ywExceptionPath);
		// 获得预受理ID
		String approvalId = this.getApprovalId(files[i]);
		xmlHeadKeyValueMap.put("approvalId", approvalId);
		this.writeFeedbackXML(this.createFeedbackXML(xmlHeadKeyValueMap),ywFeedbackPath, files[i]);
	}
	
}
